/**
 * @file CCmdLineParser.cpp Implementácia triedy CCmdLineParser.
 *
 * @author Martin Kosorinský.
 * @date 8.11.2009.
 */

#include "CCmdLineParser.hpp"

bool CCmdLineParser::isSet(char flag) {

    if (flagsStr.find(flag) == string::npos) {
        cerr << "Error: '" << __FUNCTION__ << "': Parameter " << flag << " nie je povoleny!" << endl;
        return false;
    }
    return (values.find(flag) != values.end());
}

char* CCmdLineParser::getValue(char flag) {
    map<char, char*>::const_iterator it;
    char* retVal  = NULL;

    string str  = string(1, flag).append(":");

    if ((flagsStr.find(str) != string::npos) && isSet(flag)) {
        if ((it = values.find(flag)) != values.end()) {
            retVal = it->second;
        }
        else {
            cerr << "Error: '" << __FUNCTION__ << "': Hodnota parametra " << flag << " nebola najdena!" << endl;
            exit(EXIT_FAILURE);
        }
    }

    if (retVal == NULL) {
        cerr << "Error: '" << __FUNCTION__ << "': Parameter " << flag << " nema hodnotu!" << endl;
        exit(EXIT_FAILURE);
    }

    return retVal;
}

CCmdLineParser::CCmdLineParser(int argc, char* argv[], char* flagsList) {

    flagsStr = string(flagsList);
    int flagsLen = strlen(flagsList);
    char * buffer = NULL;

    bool found = false;

    for (int i = 1; i < argc; i++) {
        if (argv[i][0] == '-') {
            if (strlen(argv[i]) == 2) {
                found = false;
                for (int j = 0; j < flagsLen; j++) {
                    if (!isalpha(flagsList[j])) {
                        continue;
                    }
                    if (argv[i][1] == flagsList[j]) {
                        // najdeny prepinac je v zozname
                        // zaznacime jeho najdenie
                        found = true;

                        if (((j + 1) < flagsLen) && (flagsList[j+1] == ':')) {
                            // prepinac by mal mat hodnotu .. overujeme
                            if (((i + 1) < argc)) {
                                buffer = new char[strlen(argv[i+1]) + 1];
                                strcpy(buffer, argv[i+1]);
                                values[(flagsList[j])] = buffer;
                                i++;
                            }
                            else {
                                cerr << "Error: '" << __FUNCTION__ << "': Chybajuca hodnota k prepinacu: " << flagsList[j] << endl;
                                exit(EXIT_FAILURE);
                            }
                        }
                        else {
                            values[(flagsList[j])] = NULL;
                        }
                        // ak sme tu, nasli sme prepinac v zozname, koncime prehladavanie
                        break;
                    }
                }
                if (!found)  {
                    cerr << "Error: '" << __FUNCTION__ << "': Neznamy parameter: " << argv[i] << endl;
                    exit(EXIT_FAILURE);
                }

            }
            else if (strlen(argv[i]) > 2) {
                for (int k = 1; k < (int)strlen(argv[i]); k++) {
                    // prechadzame vsetky prepinace
                    int posInFlagList = -1;
                    for (int j = 0; j < flagsLen; j++) {
                        if (flagsList[j] == argv[i][k]) {
                            posInFlagList = j;
                            break;
                        }
                    }
                    // este overime, ci je to bezhodnotovy parameter
                    if ((posInFlagList != -1) && (posInFlagList >= (flagsLen - 1) || flagsList[posInFlagList+1] != ':')) {
                        values[(flagsList[posInFlagList])] = NULL;
                    }
                    else {
                        cerr << "Error: '" << __FUNCTION__ << "': Hodnotovy prepinac -" << argv[i][k] << " sa nemoze nachadzat v skupine (musi byt samostatny)!" << endl;
                        exit(EXIT_FAILURE);
                    }
                }
            }
            else {
                cerr << "Error: '" << __FUNCTION__ << "': Neznamy parameter (viac prepinacov v skupine...): " << argv[i] << endl;
                exit(EXIT_FAILURE);
            }
        }
        else {
            cerr << "Error: '" << __FUNCTION__ << "': Neznamy parameter: " << argv[i] << endl;
            exit(EXIT_FAILURE);
        }
    }
}

CCmdLineParser::~CCmdLineParser() {
    map<char, char*>::const_iterator it;
    for (it = values.begin(); it != values.end(); it++) {
        delete[] it->second;
    }
}
